package com.xiaolee.hotool.json;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;

import java.util.List;

public class JsonTree {
    private TreeNode root;

    /**
     * 创建 json tree
     *
     * @param source
     * @return
     */
    public static JsonTree build(JSONObject source) {
        JsonTree tree = emptyTree();
        build(tree.root, source);

        return tree;
    }

    /**
     * 创建 json object
     *
     * @return
     */
    public JSONObject toJsonObject() {
        if (root == null) {
            return null;
        }

        JSONObject json = new JSONObject();
        for (TreeNode item : root.children()) {
            json.putOnce(item.getName(), item.value());
        }

        return json;
    }

    /**
     * 设置 json path value
     *
     * @param path
     */
    public void putByPath(String path, Object value) {
        List<PathSegment> segments = new JsonPathResolver(path).resolve();
        root.putByPath(new PathIterator(segments), value);
    }


    private static void build(TreeNode root, JSONObject source) {
        if (source == null) {
            return;
        }

        for (String key : source.keySet()) {
            Object value = source.get(key);
            if (value == null) {
                ValueTreeNode valueNode = new ValueTreeNode();
                valueNode.setName(key);
                valueNode.setValue(null);
                root.children().add(valueNode);
            } else if (value instanceof JSONObject) {
                MapTreeNode mapNode = new MapTreeNode();
                mapNode.setName(key);
                root.children().add(mapNode);
                build(mapNode, (JSONObject) value);
            } else if (value instanceof JSONArray) {
                ListTreeNode listNode = new ListTreeNode();
                listNode.setName(key);
                root.children().add(listNode);

                build(listNode, (JSONArray) value);
            } else {
                ValueTreeNode valueNode = new ValueTreeNode();
                valueNode.setName(key);
                valueNode.setValue(value);
                root.children().add(valueNode);
            }


        }
    }

    private static void build(TreeNode root, JSONArray source) {
        if (!source.isEmpty()) {
            for (int i = 0; i < source.toArray().length; i++) {
                Object value = source.get(i);
                if (value == null) {
                    root.children().set(i, null);
                } else if (value instanceof JSONObject) {
                    MapTreeNode mapNode = new MapTreeNode();
                    mapNode.setName(String.valueOf(i));
                    root.children().add(mapNode);
                    build(mapNode, (JSONObject) value);
                } else if (value instanceof JSONArray) {
                    ListTreeNode listNode = new ListTreeNode();
                    listNode.setName(String.valueOf(i));
                    root.children().add(listNode);
                    build(listNode, (JSONArray) value);
                } else {
                    ValueTreeNode valueNode = new ValueTreeNode();
                    valueNode.setName(String.valueOf(i));
                    valueNode.setValue(value);
                    root.children().add(valueNode);
                }
            }
        }
    }


    private static JsonTree emptyTree() {
        JsonTree tree = new JsonTree();
        tree.root = new MapTreeNode();
        return tree;
    }
}
